<?php

namespace C\M;

use C\L\Model;
use C\M\User;
use C\M\UserAddress;

class GroupBuyingUserOrder extends Model
{

    public function initialize()
    {
        $this->belongsTo(
            'user_id',
            'C\M\User',
            'uid',
            ['alias' => 'User']
        );
        $this->belongsTo(
            'group_buying_order_id',
            'C\M\GroupBuyingOrder',
            'id',
            ['alias' => 'GroupBuyingOrder']
        );
        $this->belongsTo(
            'address_id',
            'C\M\UserAddress',
            'id',
            ['alias' => 'Address']
        );
    }

    public function beforeCreate()
    {
        $otherInfo = json_decode($this->other_info, true);
        ($otherInfo['is_generated'] ?? false)
        ? $this->beforeCreateFakeUserOrder()
        : $this->beforeCreateRealUserOrder();
    }

    public function afterCreate()
    {
        $otherInfo = json_decode($this->other_info, true);
        ($otherInfo['is_generated'] ?? false)
        ? $this->afterCreateFakeUserOrder()
        : $this->afterCreateRealUserOrder();
    }

    public function beforeValidationOnCreate()
    {
        $this->sn = (new \DateTime())->format('YmdHisu');
        $this->addtime = $this->uptime = time();
        return true;
    }

    public function beforeValidationOnUpdate()
    {
        $this->uptime = time();
        return true;
    }

    private function beforeCreateRealUserOrder()
    {
        $orderOtherInfo = json_decode($this->groupBuyingOrder->other_info, true);
        unset($orderOtherInfo['is_generated']);

        $address = UserAddress::findFirst([
        'id = ' . $this->address_id,
        'columns' => ['id', 'name', 'tel', 'area_code', 'province', 'city', 'county', 'address'],
        ]);

        $member = $this->getUser([
        'columns' => ['uid', 'mobile']
        ]);

        $newOtherInfo = [
        'address' => $address->toArray(),
        'member'  => $member,
        ];

        $oldOtherInfo = json_decode($this->other_info ?? null, true) ?? [];

        $this->other_info = json_encode(array_merge($oldOtherInfo, $orderOtherInfo, $newOtherInfo));

        $quantity = (float)$this->quantity ?? 0;
        $price    = (float)$orderOtherInfo['goods']['price'] ?? 0;

        $total = $quantity * $price;
        $this->amount = $total;
        $this->payment_amount = $total;
    }

    private function beforeCreateFakeUserOrder()
    {
        $orderOtherInfo = json_decode($this->groupBuyingOrder->other_info, true);
        unset($orderOtherInfo['is_generated']);

        $oldOtherInfo = json_decode($this->other_info ?? null, true) ?? [];

        $this->other_info = json_encode(array_merge($oldOtherInfo, $orderOtherInfo));

        $quantity = (float)$this->quantity ?? 0;
        $price    = (float)$orderOtherInfo['goods']['price'] ?? 0;

        $total = $quantity * $price;
        $this->amount = $total;
        $this->payment_amount = $total;
    }

    private function afterCreateRealUserOrder()
    {
        $this->checkAndUpdateOrder();
        $this->updateUserBalance();
        $this->dispatchSuperiorReward();
    }

    private function afterCreateFakeUserOrder()
    {
        $this->checkAndUpdateOrder();
    }

    private function checkAndUpdateOrder()
    {
        $order = $this->groupBuyingOrder;
        $orderOtherInfo = json_decode($order->other_info, true);

        $sum = 1 + GroupBuyingUserOrder::sum([
            'group_buying_order_id = ' . $this->group_buying_order_id,
            'column' => 'quantity',
        ]);

        if ($sum < $orderOtherInfo['group_buying']['quantity_max']) {
            return;
        }

        $order->state = 'success';
        $result = $order->save();
        if (!$result) {
            throw new \Exception('更新团购信息失败');
        }
    }

    private function updateUserBalance()
    {
        if (!$this->di['s_user']->updateBalance(
            $this->user_id,
            -$this->payment_amount,
            'confirm_group_buying_user_order',
            "参与团购:{$this->sn}",
            $this->id,
        )) {
            throw new \Exception('更新用户余额失败');
        }
    }

    private function dispatchSuperiorReward()
    {
        $user = User::findFirst([
            'conditions' => 'uid = :user_id:',
            'bind' => ['user_id' => $this->user_id],
        ]);
        $superior = $this->di['s_user']->getSuperior($this->user_id);
        if (!$superior) {
            return false;
        }

        $config = $this->di['s_config']->get('reward');
        $rate = ($config['group_buying_confirm_user_order_superior_money'] ?? 0) / 100;
        $amount = $this->amount * $rate;
        $title = '下级 ' . $user->getMosaicTel() . ' 参与团购获得奖励';

        $result = $this->di['s_funds']->add(
            $superior->uid,
            $amount,
            'money',
            'group_buying_confirm_user_order_superior_reward',
            $title,
            $this->id,
            'D',
        );

        if (!$result) {
            throw new \Exception('流水添加失败');
        }

        return true;
    }
}
